home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / server~1.zip / _OBSERVE.QC < prev    next >
Text File  |  1996-10-04  |  16KB  |  495 lines

  1. /*
  2. **
  3. ** _observe.qc (Observer Code, 1.7)
  4. **
  5. ** Copyright (C) 1996 Johannes Plass
  6. ** 
  7. ** This program is free software; you can redistribute it and/or modify
  8. ** it under the terms of the GNU General Public License as published by
  9. ** the Free Software Foundation; either version 2 of the License, or
  10. ** (at your option) any later version.
  11. ** 
  12. ** This program is distributed in the hope that it will be useful,
  13. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. ** GNU General Public License for more details.
  16. **
  17. ** You should have received a copy of the GNU General Public License
  18. ** along with this program; if not, write to the Free Software
  19. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. ** 
  21. ** Author:   Johannes Plass (plass@dipmza.physik.uni-mainz.de)
  22. **
  23. */
  24.  
  25. //==============================================================
  26. //   Defaults
  27. //==============================================================
  28.  
  29. // By default pressing 'jump' respawns a player, pressing fire
  30. // changes to the next view. Setting OBSERVER_JUMP_RESPAWNS to 0
  31. // in the next line inverts this behaviour.
  32.  
  33. float OBSERVER_JUMP_RESPAWNS = 1;
  34.  
  35. //==============================================================
  36. //   ObserverInfo
  37. //==============================================================
  38.  
  39. void(entity player) ObserverInfo =
  40. {
  41.   if (!USE_MODULE_OBSERVER) return;
  42.               // 123456789#123456789#123456789#12345678
  43.   sprint(player,"£");
  44.   sprint(player," Observer");
  45.   sprint(player,          " allows you to peep.\n");
  46.   sprint(player,"  Type 'help-observer' for help.\n");
  47. };
  48.  
  49. //==============================================================
  50. //   ObserverInit
  51. //==============================================================
  52.  
  53. void(entity player) ObserverInit =
  54. {
  55.   if (!USE_MODULE_OBSERVER) return;
  56.   stuffcmd(player,"alias help-observer \"impulse 205\";\n");
  57.   stuffcmd(player,"alias observer-noclip \"impulse 206\";\n");
  58. };
  59.  
  60. //==============================================================
  61. //   ObserverActiveMessage
  62. //==============================================================
  63.  
  64. void(entity player) ObserverActiveMessage =
  65. {
  66.   if (!USE_MODULE_OBSERVER) return;
  67.               // 123456789#123456789#123456789#12345678
  68.   sprint(player,"  Observer      (help-observer)\n");
  69. };
  70.  
  71. //==============================================================
  72. //   ObserverHelp
  73. //==============================================================
  74.  
  75. void(entity player) ObserverHelp =
  76. {
  77.   if (!USE_MODULE_OBSERVER) return;
  78.  
  79.               // 123456789#123456789#123456789#12345678
  80.   sprint(player,"Observer:");
  81.   sprint(player,          " allows to watch the\n");
  82.   sprint(player,"ongoing madness.\n");
  83.   sprint(player,"As observer you can:\n");
  84.   sprint(player," - fly around.\n");
  85.   sprint(player," - move to another watch-spot by \n");
  86.   if (OBSERVER_JUMP_RESPAWNS)
  87.     sprint(player,"   pressing the fire-button. \n");
  88.   else
  89.     sprint(player,"   pressing the jump-button. \n");
  90.   sprint(player," - join the game as regular player\n");
  91.   if (OBSERVER_JUMP_RESPAWNS)
  92.     sprint(player,"   by pressing the jump-button. \n");
  93.   else
  94.     sprint(player,"   by pressing the fire-button. \n");
  95.   sprint(player,"Use the command 'observer-noclip' to\n");
  96.   sprint(player,"turn clipping on or off.\n");
  97.   if (OBSERVER_JUMP_RESPAWNS)
  98.     sprint(player,"Press the fire-button to become an\n");
  99.   else
  100.     sprint(player,"Press the jump-button to become an\n");
  101.   sprint(player,"observer when you are dead.\n");
  102. };
  103.  
  104. //==============================================================
  105. //   ObserverThink
  106. //==============================================================
  107.  
  108. void () ObserverThink =
  109. {
  110.   //dprint("ObserverThink: executing\n");
  111.  
  112.   if (!USE_MODULE_OBSERVER) return;
  113.  
  114.   self.weaponmodel = "";
  115.   self.weaponframe = 0;
  116.   self.flags = self.flags | FL_ONGROUND;
  117.   
  118.   { 
  119.     local float invcos,nv,nvp,nvpmax,nvs,nsp,sp,svz;
  120.     local vector f,vp,vs;
  121.     
  122.     svz = self.velocity_z * 0.75;
  123.     self.velocity_z = 0;
  124.     
  125.     // v_forward is already normalized
  126.     f_x = v_forward_x; 
  127.     f_y = v_forward_y; 
  128.     f_z = 0;
  129.     invcos = vlen(f); if (invcos) invcos= 1/invcos; else invcos=0;
  130.     f = f*invcos; // normalize f
  131.     
  132.     sp = f * self.velocity;
  133.     vp = sp*f;
  134.     nvp = vlen(vp); if (sp<0) nvp = nvp*(-1);
  135.     vs = self.velocity - vp;
  136.     
  137.     vp = v_forward * (nvp * invcos);
  138.     vp_z = vp_z + svz;
  139.     nvp = vlen(vp);
  140.     nvpmax = (320 - 100*(v_forward * '0 0 1'));
  141.     if (nvp > nvpmax) { vp = vp * (nvpmax/nvp); }
  142.     
  143.     self.velocity = vp + vs;
  144.   }
  145.   
  146.   {
  147.     local entity e;
  148.     local float cont;
  149.     e = findradius(self.origin,75);
  150.     if (e) { cont = TRUE;  }
  151.     else   { cont = FALSE; }
  152.     while (cont) {
  153.       // dprint(e.classname); dprint("\n");
  154.       if (e.classname == "door") {
  155.     ObserverTeleportThroughDoor(self,e);
  156.     cont = FALSE;
  157.       }
  158.       if (e.classname == "trigger_teleport") {
  159.     ObserverTeleportThroughTeleporter(self,e);
  160.     cont = FALSE;
  161.       }
  162.       e = e.chain;
  163.       if (!e) { cont = FALSE; }
  164.     }
  165.   }
  166.   
  167.   if (self.observer_status & OBSERVER_BECOME_OBSERVER) {
  168.     ObserverBecomeObserver(self);
  169.     return;
  170.   }
  171.   
  172.   if (self.observer_status & OBSERVER_NEXTVIEW) {
  173.     self.observer_pos_num = self.observer_pos_num + 1;
  174.     ObserverSetPlayerPos(self);
  175.     self.observer_status = self.observer_status - OBSERVER_NEXTVIEW;
  176.     return;
  177.   }
  178.   
  179.   if (self.observer_status & OBSERVER_TOGGLE_NOCLIP) {
  180.     if (self.movetype == MOVETYPE_FLY) {
  181.       self.movetype = MOVETYPE_NOCLIP;
  182.       sprint(self,"noclip on\n");
  183.     } else {
  184.       self.movetype = MOVETYPE_FLY;
  185.       sprint(self,"noclip off\n");
  186.     }
  187.     self.observer_status = self.observer_status - OBSERVER_TOGGLE_NOCLIP;
  188.   }
  189.   
  190.   if (self.button0) {
  191.     self.observer_status = OBSERVER_BUTTON0;
  192.     return;
  193.   }
  194.   else if (self.button1) {
  195.     self.observer_status = 0;
  196.     return;
  197.   }
  198.   else if (self.button2) {
  199.     self.observer_status = OBSERVER_BUTTON2;
  200.     return;
  201.   }
  202.   
  203.   if (OBSERVER_JUMP_RESPAWNS) {
  204.     if (self.observer_status & OBSERVER_BUTTON0) {
  205.       self.observer_status = OBSERVER_NEXTVIEW;
  206.       return;
  207.     }
  208.     if (self.observer_status & OBSERVER_BUTTON2) {
  209.       self.observer_status  = OBSERVER_RESPAWN;
  210.       return;
  211.     }
  212.   } else {
  213.     if (self.observer_status & OBSERVER_BUTTON2) {
  214.       self.observer_status = OBSERVER_NEXTVIEW;
  215.       return;
  216.     }
  217.     if (self.observer_status & OBSERVER_BUTTON0) {
  218.       self.observer_status  = OBSERVER_RESPAWN;
  219.       return;
  220.     }
  221.   }
  222.   
  223.   if (self.observer_status & OBSERVER_RESPAWN) {
  224.     respawn();
  225.     // remove flag must be set after respawn()
  226.     PlayerStatusRemoveFlag(self,PLAYER_IS_OBSERVER);
  227.     return;
  228.   }
  229. };
  230.  
  231. //==============================================================
  232. //   ObserverDeathThink
  233. //==============================================================
  234.  
  235. float() ObserverDeathThink = 
  236. {
  237.   if (!USE_MODULE_OBSERVER) return(0);
  238.   
  239.   if (self.button0) {
  240.     self.observer_status = OBSERVER_BUTTON0;
  241.   }
  242.   else if (self.button1) {
  243.     self.observer_status = 0;
  244.   }
  245.   else if (self.button2) {
  246.     self.observer_status = OBSERVER_BUTTON2;
  247.   }
  248.   else if (self.observer_status & (OBSERVER_BUTTON0 | OBSERVER_BUTTON2)) {
  249.     if (OBSERVER_JUMP_RESPAWNS) {
  250.       if (self.observer_status & OBSERVER_BUTTON0) self.observer_status = OBSERVER_BECOME_OBSERVER;
  251.       else self.observer_status = 0;
  252.     } else {
  253.       if (self.observer_status & OBSERVER_BUTTON2) self.observer_status = OBSERVER_BECOME_OBSERVER;
  254.       else self.observer_status = 0;
  255.     }
  256.     respawn();
  257.   }
  258.   self.button0 = 0;
  259.   self.button1 = 0;
  260.   self.button2 = 0;
  261.   return(1);
  262. };
  263.  
  264. //==============================================================
  265. //   ObserverBecomeObserver
  266. //==============================================================
  267.  
  268. void(entity player) ObserverBecomeObserver =
  269. {
  270.   //dprint("ObserverBecomeObserver: executing\n");//#jp#(debug)
  271.   
  272.   player.armorvalue       = 0;
  273.   player.items            = 0;
  274.   player.health           = 999;
  275.   player.ammo_shells      = 0;
  276.   player.ammo_nails       = 0;
  277.   player.ammo_rockets     = 0;
  278.   player.ammo_cells       = 0;
  279.   player.weapon           = 0;
  280.   player.currentammo      = 1;
  281.   player.takedamage       = DAMAGE_NO;
  282.   player.solid            = SOLID_NOT;
  283.   player.movetype         = MOVETYPE_FLY;
  284.   player.deadflag         = DEAD_NO;
  285.   
  286.   setmodel (player, string_null);
  287.   
  288.   player.weaponmodel      = "";
  289.   player.weaponframe      = 0;
  290.   
  291.   player.observer_pos_num = 0;
  292.   player.observer_status  = 0;
  293.   player.observer_pos_num = 1 + random() * 4;
  294.   ObserverSetPlayerPos(player);
  295. };
  296.  
  297.  
  298. //==============================================================
  299. //   ObserverFindPos
  300. //==============================================================
  301.  
  302. entity(entity player) ObserverFindPos =
  303. {
  304.   local entity spot;
  305.   local float cont;
  306.   
  307.   //dprint("ObserverFindPos: executing\n");
  308.   
  309.   cont = 1;
  310.   while (cont<3) {
  311.     if      (player.observer_pos_num <= 0)  player.observer_pos_num = 1;
  312.     else if (player.observer_pos_num >= 21) player.observer_pos_num = 1;
  313.     
  314.     if (player.observer_pos_num <= 5) {
  315.       spot = find (world, classname, "info_intermission");
  316.       if (player.observer_pos_num >= 2 && !(!spot))  spot = find (spot,  classname, "info_intermission");
  317.       if (player.observer_pos_num >= 3 && !(!spot))  spot = find (spot,  classname, "info_intermission");
  318.       if (player.observer_pos_num >= 4 && !(!spot))  spot = find (spot,  classname, "info_intermission");
  319.       if (!spot) player.observer_pos_num = 5;
  320.     }
  321.     if (player.observer_pos_num >= 5) {
  322.       spot = find (world, classname, "info_player_deathmatch");
  323.       if (player.observer_pos_num >=  6 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  324.       if (player.observer_pos_num >=  7 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  325.       if (player.observer_pos_num >=  8 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  326.       if (player.observer_pos_num >=  9 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  327.       if (player.observer_pos_num >= 10 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  328.       if (player.observer_pos_num >= 11 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  329.       if (player.observer_pos_num >= 12 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  330.       if (player.observer_pos_num >= 13 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  331.       if (player.observer_pos_num >= 14 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  332.       if (player.observer_pos_num >= 15 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  333.       if (player.observer_pos_num >= 16 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  334.       if (player.observer_pos_num >= 17 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  335.       if (player.observer_pos_num >= 18 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  336.       if (player.observer_pos_num >= 19 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  337.       if (player.observer_pos_num >= 20 && !(!spot)) spot = find (spot,  classname, "info_player_deathmatch");
  338.       if (!spot) player.observer_pos_num = 21;
  339.     }
  340.     if (player.observer_pos_num >= 21) {
  341.       spot = find (world, classname, "info_player_start");
  342.       player.observer_pos_num = 21;
  343.     }
  344.     if (!spot) {
  345.       player.observer_pos_num = 0;
  346.     } else {
  347.       cont = 10;
  348.     }
  349.     cont = cont + 1;
  350.   }
  351.   if (!spot) error ("ObserverFindPos: could not find start pos");
  352.   return spot;
  353. };
  354.  
  355. //==============================================================
  356. //   ObserverSetPlayerPos
  357. //==============================================================
  358.  
  359. void(entity player) ObserverSetPlayerPos =
  360. {
  361.   local entity pos;
  362.   
  363.   //dprint("ObserverSetPlayerPos: executing\n");//#jp#(debug)
  364.   
  365.   pos = ObserverFindPos(player);
  366.   
  367.   player.angles        = player.v_angle = pos.mangle;
  368.   player.fixangle      = TRUE;         // turn this way immediately
  369.   player.view_ofs      = '0 0 12'; // must be != '0 0 0'
  370.   player.velocity      = '0 0 0';
  371.   
  372.   makevectors (player.angles);
  373.   setsize (player, '-12  -12 -12', '12 12 12');
  374.   // setsize (player, VEC_HULL_MIN, VEC_HULL_MAX);
  375.   // player.view_ofs = '0 0 22';
  376.   
  377.   // avoid stuck observers for intermission spots 
  378.   if (player.observer_pos_num <=4) setorigin (player, pos.origin + '0 0 -60');
  379.   else                             setorigin (player, pos.origin);
  380. };
  381.  
  382. //==============================================================
  383. //   ObserverNoclip
  384. //==============================================================
  385.  
  386. void(entity player) ObserverNoclip =
  387. {
  388.   if (!USE_MODULE_OBSERVER) return;
  389.   
  390.   player.observer_status = player.observer_status | OBSERVER_TOGGLE_NOCLIP;
  391. };
  392.  
  393. //==============================================================
  394. //   ObserverTeleportThroughDoor
  395. //==============================================================
  396.  
  397. void(entity player,entity door) ObserverTeleportThroughDoor =
  398. {
  399.   local entity d,d_master;
  400.   local vector dmin,dmax;
  401.   
  402.   d_master = d = door.owner;
  403.   if (d_master) {
  404.     dmin = d_master.absmin;
  405.     dmax = d_master.absmax;
  406.   } else { 
  407.     dmin = dmax = '0 0 0'; 
  408.   }
  409.   if (dmin != dmax) {
  410.     // regular doors
  411.     if (d_master.state != STATE_BOTTOM) return;
  412.     do {
  413.       // dprint (vtos(d.absmin)); dprint (" "); dprint (vtos(d.absmax)); dprint ("\n");
  414.       if (d.absmin_x < dmin_x) { dmin_x = d.absmin_x; }
  415.       if (d.absmax_x > dmax_x) { dmax_x = d.absmax_x; }
  416.       if (d.absmin_y < dmin_y) { dmin_y = d.absmin_y; }
  417.       if (d.absmax_y > dmax_y) { dmax_y = d.absmax_y; }
  418.       if (d.absmin_z < dmin_z) { dmin_z = d.absmin_z; }
  419.       if (d.absmax_z > dmax_z) { dmax_z = d.absmax_z; }
  420.       d = d.enemy; // next linked door;
  421.     } while ((d != d_master) && (d != world));
  422.   }
  423.   else {
  424.     // secret doors
  425.     // we ignore these currently
  426.     return;
  427.   }
  428.   
  429.   {
  430.     local float is_x,is_y,is_z,set;
  431.     local vector dir,or;
  432.     set = is_x = is_y = is_z = FALSE;
  433.     or = player.origin;
  434.     if (dmin_x + 15 < player.absmin_x && player.absmax_x < dmax_x - 15) is_x = TRUE;
  435.     if (dmin_y + 15 < player.absmin_y && player.absmax_y < dmax_y - 15) is_y = TRUE;
  436.     if (dmin_z + 15 < player.absmin_z && player.absmax_z < dmax_z - 15) is_z = TRUE;
  437.     // dprint("doors:  "); dprint (vtos(dmin)); dprint (" "); dprint (vtos(dmax)); dprint ("\n");
  438.     // dprint("player: "); dprint (vtos(player.absmin)); dprint (" "); dprint (vtos(player.absmax)); dprint ("\n");
  439.     if (is_x && is_y) {
  440.       // dprint("door is in xy plane\n");
  441.       if      (or_z < dmin_z) { dir = '0 0  1'; or_z = dmax_z + 25; }
  442.       else if (or_z > dmax_z) { dir = '0 0 -1'; or_z = dmin_z - 25; }
  443.       set = TRUE;
  444.     }
  445.     else if (is_x && is_z) {
  446.       // dprint("door is in xz plane\n");
  447.       if      (or_y < dmin_y) { dir = '0  1 0'; or_y = dmax_y + 25; }
  448.       else if (or_y > dmax_y) { dir = '0 -1 0'; or_y = dmin_y - 25; }
  449.       set = TRUE;
  450.     }
  451.     else if (is_y && is_z) {
  452.       // dprint("door is in yz plane\n");
  453.       if      (or_x < dmin_x) { dir = ' 1 0 0'; or_x = dmax_x + 25; }
  454.       else if (or_x > dmax_x) { dir = '-1 0 0'; or_x = dmin_x - 25; }
  455.       set = TRUE;
  456.     }
  457.       if (set) { 
  458.     local vector v;
  459.     v =  normalize(player.velocity);
  460.     if (dir * v < 0.5) return;
  461.     player.origin = or;
  462.     setorigin (player, player.origin);
  463.       }
  464.   }
  465. };
  466.  
  467. //==============================================================
  468. //   ObserverTeleportThroughTeleporter
  469. //==============================================================
  470.  
  471. void(entity player,entity tele) ObserverTeleportThroughTeleporter =
  472. {
  473.   local entity targ;
  474.   local vector v1,v2;
  475.   
  476.   v1 = ((tele.absmax + tele.absmin) * 0.5) - player.origin; normalize(v1);
  477.   v2 = player.velocity; normalize(v2);
  478.   if (v1 * v2 <= 0.1) return;
  479.   
  480.   targ = find (world, targetname, tele.target);
  481.   if (!targ) {
  482.     dprint("ObserverTeleportThroughTeleporter: couldn't find teleporter target\n");
  483.     return;
  484.   }
  485.   makevectors (targ.mangle);
  486.   setorigin (player, targ.origin);
  487.   player.angles = targ.mangle;
  488.   player.fixangle = TRUE; // turn this way immediately
  489.   player.teleport_time = time + 0.7;
  490.   player.velocity = v_forward * 300;
  491.   // player.flags = player.flags - player.flags & FL_ONGROUND;
  492. };
  493.  
  494.  
  495.